package models

import (
	"errors"
	"github.com/gorilla/sessions"
	"golang.org/x/crypto/bcrypt"
	"gorm.io/gorm"
	"hello/inits/config"
	"hello/inits/db"
	"hello/inits/session"
	captchaService "hello/lib/captcha"
	"net/http"
	"time"
)

//GORM 倾向于约定，而不是配置。默认情况下，
//GORM 使用 ID 作为主键，使用结构体名的 蛇形复数 作为表名，
//字段名的 蛇形 作为列名，并使用 CreatedAt、UpdatedAt 字段追踪创建、更新时间
type Admin struct {
	ID        uint      `gorm:"primary_key,column:id"`
	Username  string    `gorm:"column:username"`
	Password  string    `gorm:"column:password"`
	LoginTime time.Time `gorm:"column:login_time"`
	LoginNum  uint      `gorm:"column:login_num"`
	Ip        string    `gorm:"column:ip"`
}

func (Admin) TableName() string {
	return "admin"
}

func (m *Admin) Attempt(captchaId string, captcha string, username string,
	password string) (error, *Admin) {
	checkCode := captchaService.Verify(captchaId, captcha)
	if !checkCode {
		//return errors.New("验证码有误"), m
	}
	if username == "" || password == "" {
		return errors.New("账号密码不能为空"), m
	}
	admin, err := m.GetAdminByUsername(username)
	if err != nil {
		return errors.New("账号或密码有误"), m
	}
	checkStatus := m.CheckPassword(password, admin.Password)
	if !checkStatus {
		return errors.New("账号或密码有误"), m
	}
	return nil, admin
}

func (m *Admin) CheckPassword(password string, hash string) bool {
	//base64Ca
	if password == "" {
		return false
	}
	return passwordVerify(password, hash)
}

// 根据用户名获取用户
func (m *Admin) GetAdminByUsername(username string) (*Admin, error) {
	var cAdmin Admin
	err := db.DB.Model(&Admin{}).Where("username = ?", username).
		First(&cAdmin).Error
	if err != nil && err != gorm.ErrRecordNotFound {
		return nil, err
	}
	return &cAdmin, nil
}

//获取用户登录信息
func (m Admin) GetAdminBySession(r *http.Request) (*sessions.Session, error) {
	cookieName := config.GetString("COOKIE_NAME")
	sessionData, err := session.SESSION_STORE.Get(r, cookieName)
	return sessionData, err
}

//func passwordHash(password string) (string, error) {
//	bytes, err := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost)
//	return string(bytes), err
//}

func passwordVerify(password, hash string) bool {
	err := bcrypt.CompareHashAndPassword([]byte(hash), []byte(password))
	return err == nil
}
